#define _CAN_MOUDEL_
#include "candevice.h"

/*****************************************************************************//*!
   *
   * @brief can rx interrupt.   
   * @param[in]  none.
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void MSCAN_RX_IRQHandler()
{
	uint8_t Status;
	
	Status = MSCAN->CANRFLG;
	
	if(Status & MSCAN_CANRFLG_WUPIF_MASK)
	{
		__nop();
	}
	else if(Status & MSCAN_CANRFLG_CSCIF_MASK)
	{
		
	}
	else if(Status & MSCAN_CANRFLG_OVRIF_MASK)
	{
		CAN_ReadFrame(MSCAN,&CanRxFrameCur);
	}
	else if(Status & MSCAN_CANRFLG_RXF_MASK)
	{
		CAN_ReadFrame(MSCAN,&CanRxFrameCur);
	}
	else
	{
		
	}
}

/*****************************************************************************//*!
   *
   * @brief can tx interrupt.       
   * @param[in]  none.
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void MSCAN_TX_IRQHandler()
{
	__nop();
}


/*****************************************************************************//*!
   *
   * @brief can module init.     
   * @param[in]  baud - baudary.
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void CanDeviceInit(uint32_t baud)
{
//	uint32_t CalTemp;
	
	MSCAN_BaudRateSettingType CanBaud;
	
	SIM->SCGC |= SIM_SCGC_MSCAN_MASK;
	SIM->PINSEL1 &= ~SIM_PINSEL1_MSCANPS_MASK;
	
	MSCAN->CANCTL1 |= MSCAN_CANCTL1_CANE_MASK;    // enable can module
	MSCAN->CANCTL1 |= MSCAN_CANCTL1_CLKSRC_MASK;  // select busclk
	CAN_InitialModeReq(MSCAN);                    // request config mode
    //enter into Initialization mode
    while(!CAN_IsInitialMode(MSCAN));
	
	MSCAN->CANIDAR_BANK_1[0] = CAN_RX_FILTER_1_ID & 0xFF;              //receive filter config
    MSCAN->CANIDAR_BANK_1[1] = (CAN_RX_FILTER_1_ID >> 8) & 0xFF;
    MSCAN->CANIDAR_BANK_1[2] = (CAN_RX_FILTER_1_ID >> 16) & 0xFF;
    MSCAN->CANIDAR_BANK_1[3] = (CAN_RX_FILTER_1_ID >> 24) & 0xFF;
	
	MSCAN->CANIDMR_BANK_1[0] = CAN_RX_FILTER_1_ID_MASK  & 0xFF;        //receive filter mask config
    MSCAN->CANIDMR_BANK_1[1] = (CAN_RX_FILTER_1_ID_MASK  >> 8) & 0xFF;
    MSCAN->CANIDMR_BANK_1[2] = (CAN_RX_FILTER_1_ID_MASK  >> 16) & 0xFF;
    MSCAN->CANIDMR_BANK_1[3] = (CAN_RX_FILTER_1_ID_MASK  >> 24) & 0xFF;	
	
	MSCAN->CANIDAR_BANK_2[0] = CAN_RX_FILTER_2_ID & 0xFF;              //receive filter config
    MSCAN->CANIDAR_BANK_2[1] = (CAN_RX_FILTER_2_ID >> 8) & 0xFF;
    MSCAN->CANIDAR_BANK_2[2] = (CAN_RX_FILTER_2_ID >> 16) & 0xFF;
    MSCAN->CANIDAR_BANK_2[3] = (CAN_RX_FILTER_2_ID >> 24) & 0xFF;
	
	MSCAN->CANIDMR_BANK_2[0] = CAN_RX_FILTER_2_ID_MASK  & 0xFF;        //receive filter mask config
    MSCAN->CANIDMR_BANK_2[1] = (CAN_RX_FILTER_2_ID_MASK  >> 8) & 0xFF;
    MSCAN->CANIDMR_BANK_2[2] = (CAN_RX_FILTER_2_ID_MASK  >> 16) & 0xFF;
    MSCAN->CANIDMR_BANK_2[3] = (CAN_RX_FILTER_2_ID_MASK  >> 24) & 0xFF;
	
	CanBaud.BRP   = SystemBusClock / (baud * 20) - 1;                 //baud rate config
	CanBaud.SJW   = SJW_3TQ;
	CanBaud.TSEG1 = TSEG_10;
	CanBaud.TSEG2 = TSEG_7;
	CanBaud.SAMP = 1;                                                 // Bus line is sampled 3 times at the sample point 
	MSCAN->CANBTR0 = MSCAN_CANBTR0_SJW(CanBaud.SJW) | MSCAN_CANBTR0_BRP(CanBaud.BRP);
    MSCAN->CANBTR1 = MSCAN_CANBTR1_TSEG1(CanBaud.TSEG1) | MSCAN_CANBTR1_TSEG2(CanBaud.TSEG2);
   	if(CanBaud.SAMP)
		MSCAN->CANBTR1 |= MSCAN_CANBTR1_SAMP_MASK;
   	else
		MSCAN->CANBTR1 &= ~MSCAN_CANBTR1_SAMP_MASK;
	
	//operation mode config
	
	MSCAN->CANCTL0 &= ~MSCAN_CANCTL0_TIME_MASK;                       //disable inner timer 
	CAN_ListenModeDisable(MSCAN);                                     //disable listen mode ,can module will ack the bus
#if CAN_TEST_MODE > 0
	CAN_LoopModeEn(MSCAN);                                            //enable receive-self
#else
	CAN_LoopModeDisable(MSCAN);                                       //disable receive-self
#endif	
	CAN_StopInWaitModeDisable(MSCAN);                                 //runing in wait mode 
	CAN_WakeUpModeNoFilter(MSCAN);                                    //
	CAN_BusOffAutoRecovery(MSCAN);
	
	CAN_SetIDAMode(MSCAN,ID_ACCEPT_MODE_FOUR16);
	
	// exit initialization mode
    CAN_NormalModeReq(MSCAN);
    //wait to exit initialization mode
    while(CAN_IsInitialMode(MSCAN));

	MSCAN->CANRIER =    (0 << MSCAN_CANRIER_WUPIE_SHIFT) |            //wake up interrupt
						(1 << MSCAN_CANRIER_CSCIE_SHIFT) |            //rx status change interrupt
						(3 << MSCAN_CANRIER_RSTATE_SHIFT)|            //receive status change mode
						(3 << MSCAN_CANRIER_TSTATE_SHIFT)|            //hardware status change mode
						(1 << MSCAN_CANRIER_OVRIE_SHIFT) |            //buffer over flow interrupt
						(1 << MSCAN_CANRIER_RXFIE_SHIFT) ;            //buffer full interrupt
	MSCAN->CANTIER =    0;                                            //tx buffer interrupt
	
	NVIC_SetPriority(MSCAN_RX_IRQn, 0xFF);
	NVIC_ClearPendingIRQ(MSCAN_RX_IRQn);
	NVIC_EnableIRQ(MSCAN_RX_IRQn);
	
	NVIC_SetPriority(MSCAN_TX_IRQn, 0xFF);
	NVIC_ClearPendingIRQ(MSCAN_TX_IRQn);
	NVIC_DisableIRQ(MSCAN_TX_IRQn);
}


/*****************************************************************************//*!
   *
   * @brief read a frame data from receiver buffer
   *        
   * @param[in] pCANx   point to CAN module type.
   * @param[in] pTxFrame point to tx frame
   *
   * @return send status, fail or success
   *
   * @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t CAN_SendFrame(MSCAN_Type *pCANx,MSCAN_FramePtr pTxFrame)
{
	MSCAN_RegisterFrameType pFrameBuff;
	
	pFrameBuff.EIDR0 = 0;
	pFrameBuff.EIDR1 = 0;
	pFrameBuff.EIDR2 = 0;
	pFrameBuff.EIDR3 = 0;
	
	if(pTxFrame->bIsExtOrStand)
	{
		pFrameBuff.EIDR1 |= MSCAN_TEIDR1_TEIDE_MASK;
		pFrameBuff.EIDR0 |= ( ((pTxFrame->ID_Type.ID) >> 21) << MSCAN_TEIDR0_TEID28_TEID21_SHIFT) & MSCAN_TEIDR0_TEID28_TEID21_MASK;
		pFrameBuff.EIDR1 |= ( ((pTxFrame->ID_Type.ID) >> 18) << MSCAN_TEIDR1_TEID20_TEID18_SHIFT) & MSCAN_TEIDR1_TEID20_TEID18_MASK;
		pFrameBuff.EIDR1 |= ( ((pTxFrame->ID_Type.ID) >> 15) << MSCAN_TEIDR1_TEID17_TEID15_SHIFT) & MSCAN_TEIDR1_TEID17_TEID15_MASK;
		pFrameBuff.EIDR2 |= ( ((pTxFrame->ID_Type.ID) >> 7 ) << MSCAN_TEIDR2_TEID14_TEID7_SHIFT ) & MSCAN_TEIDR2_TEID14_TEID7_MASK ;
		pFrameBuff.EIDR3 |= ( ((pTxFrame->ID_Type.ID) >> 0 ) << MSCAN_TEIDR3_TEID6_TEID0_SHIFT  ) & MSCAN_TEIDR3_TEID6_TEID0_MASK  ;
		pFrameBuff.EIDR1 |= MSCAN_TEIDR1_TSRR_MASK;
	}
	else
	{
		pFrameBuff.EIDR0 |= ( (pTxFrame->ID_Type.ID) >> 3) & MSCAN_TSIDR0_TSID10_TSID3_MASK;
		pFrameBuff.EIDR1 |= ( (pTxFrame->ID_Type.ID) << 5) & MSCAN_TSIDR1_TSID2_TSID0_MASK;
	}
	
	if(pTxFrame->bIsRemoteFrame)
	{
		pFrameBuff.EIDR1  |= MSCAN_TEIDR1_TSRR_MASK;
		pFrameBuff.EIDR3  |= MSCAN_TEIDR3_TERTR_MASK;
	}
	
	pFrameBuff.DLR     = pTxFrame->DLR & 0x0F;
	pFrameBuff.BPR     = pTxFrame->BPR;
	
	pFrameBuff.EDSR[0] = pTxFrame->DSR[0];
	pFrameBuff.EDSR[1] = pTxFrame->DSR[1];
	pFrameBuff.EDSR[2] = pTxFrame->DSR[2];
	pFrameBuff.EDSR[3] = pTxFrame->DSR[3];
	pFrameBuff.EDSR[4] = pTxFrame->DSR[4];
	pFrameBuff.EDSR[5] = pTxFrame->DSR[5];
	pFrameBuff.EDSR[6] = pTxFrame->DSR[6];
	pFrameBuff.EDSR[7] = pTxFrame->DSR[7];
	
	
	return (CAN_LoadOneFrameToBuff(pCANx, &pFrameBuff));
	
}

/*****************************************************************************//*!
   *
   * @brief read a frame data from receiver buffer
   *        
   * @param[in] pCANx   point to CAN module type.
   *
   * @return send status, fail or success
   *
   * @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t CAN_ReadFrame(MSCAN_Type *pCANx,MSCAN_FramePtr pRxFrame)
{
	IDR1_3_UNION sIDR1;
	IDR1_3_UNION sIDR3;
    uint8_t i;
	if(CAN_IsRxBuffFull(pCANx))
	{
  		sIDR1.Bytes = CAN_ReadIDR1Reg(pCANx);
		sIDR3.Bytes = CAN_ReadIDR3Reg(pCANx);
		
		pRxFrame->bIsExtOrStand = sIDR1.IDR1.R_TEIDE;
		pRxFrame->ID_Type.ID = 0;
		if(pRxFrame->bIsExtOrStand)
		{
			pRxFrame->bIsRemoteFrame = sIDR3.IDR3.ERTR;
			pRxFrame->ID_Type.ExtID.EID28_21 = CAN_ReadIDR0Reg(pCANx);
			pRxFrame->ID_Type.ExtID.EID20_18 = sIDR1.IDR1.EID20_18_OR_SID2_0;
			pRxFrame->ID_Type.ExtID.EID17_15 = sIDR1.IDR1.EID17_15;
			pRxFrame->ID_Type.ExtID.EID14_7 = CAN_ReadIDR2Reg(pCANx);
			pRxFrame->ID_Type.ExtID.EID6_0 = sIDR3.IDR3.EID6_0;
		}
		else
		{
			pRxFrame->bIsRemoteFrame = sIDR1.IDR1.R_TSRR;
			pRxFrame->ID_Type.StandID.EID2_0 = sIDR1.IDR1.EID20_18_OR_SID2_0;
			pRxFrame->ID_Type.StandID.EID10_3 = CAN_ReadIDR0Reg(pCANx);
		}
		
		pRxFrame->DLR = pCANx->RDLR&0x0F;
        for(i=0;i<pRxFrame->DLR;i++)
        {
            pRxFrame->DSR[i] = pCANx->REDSR[i];
        }

		// read stamps 
		pRxFrame->u8TSRH = CAN_ReadTTSRHReg(pCANx);
		pRxFrame->u8TSRL = CAN_ReadTTSRLReg(pCANx);

		// clear receiver full flag
		CAN_ClearRXF_Flag(pCANx);
		return TRUE;
	}

	// return data frame
	return FALSE;
}
